package com.novel.disk.controller;

import com.novel.disk.common.ApiUtils;
import com.novel.disk.common.BaseController;
import com.novel.disk.common.FileUtils;
import com.novel.disk.common.Result;
import com.novel.disk.entity.FileEntity;
import com.novel.disk.service.FileService;
import lombok.SneakyThrows;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

/**
 * 文件
 *
 * @author novel
 * @date 2020/7/13
 */
@RestController
@RequestMapping("/file")
public class FileController extends BaseController {
    private final FileService fileService;

    public FileController(FileService fileService) {
        this.fileService = fileService;
    }

    /**
     * 新建目录
     *
     * @param dirName 目录名称
     * @param pid     当前目录的id
     * @return 结果
     */
    @PostMapping("/mkdir")
    public Result mkdir(String dirName, Long pid) {
        return toAjax(fileService.mkdir(dirName, pid, getUserId()));
    }

    /**
     * 列出某个目录下所有文件和文件夹
     *
     * @param fileEntity 查询条件
     * @return 结果
     */
    @GetMapping("/listDir")
    public Result listDir(FileEntity fileEntity) {
        fileEntity.setUserId(getUserId());
        return toAjax(fileService.listDir(fileEntity));
    }


    @GetMapping("/listDirTree")
    public Result listDirTree() {
        return toAjax(fileService.listDirTree(getUserId()));
    }

    /**
     * 上传文件
     *
     * @param file 上传的文件
     * @param pid  文件目录
     * @return 结果
     */
    @PostMapping("/upLoad")
    public Result upLoad(MultipartFile file, @RequestParam(value = "pid", required = false) Long pid) {
        return toAjax(fileService.upLoad(file, pid, getUserId()));
    }


    /**
     * 删除指定资源
     *
     * @param sourceListId 资源id集合
     * @return 结果
     */
    @DeleteMapping("/remove")
    public Result remove(@RequestParam("sourceListId") Long[] sourceListId) {
        return toAjax(fileService.remove(sourceListId, getUserId()));
    }

    /**
     * 重命名
     *
     * @param id   资源id
     * @param name 资源名称
     * @return 结果
     */
    @PutMapping("/rename")
    public Result rename(@RequestParam("id") Long id, @RequestParam("name") String name) {
        return toAjax(fileService.rename(id, name, getUserId()));
    }

    /**
     * 资源复制
     *
     * @param sourceListId 资源id集合
     * @param targetId     目标目录
     * @return 结果
     */
    @PostMapping("copyDir")
    public Result copyDir(@RequestParam("sourceListId") Long[] sourceListId, @RequestParam("targetId") Long targetId) {
        return toAjax(fileService.copyDir(sourceListId, targetId, getUserId()));
    }

    /**
     * 资源移动
     *
     * @param sourceListId 资源id集合
     * @param targetId     目标目录
     * @return 结果
     */
    @PostMapping("/moveDir")
    public Result moveDir(@RequestParam("sourceListId") Long[] sourceListId, @RequestParam("targetId") Long targetId) {
        return toAjax(fileService.moveDir(sourceListId, targetId, getUserId()));
    }

    @PostMapping("/getDownloadUrl")
    public Result getDownloadUrl(@RequestParam("fileId") Long fileId) {
        FileEntity fileEntity = fileService.getDownloadUrl(fileId);
        if (fileEntity != null) {
            Map<Object, Object> map = new HashMap<>(4);
            map.put("url", "/file/download?url=" + ApiUtils.encodeBase64(fileEntity.getUrl()) + "&exp=" + (System.currentTimeMillis() + 300000) + "&fileName=" + fileEntity.getName());
            map.put("fileId", fileEntity.getFileId());
            map.put("fileName", fileEntity.getName());
            return toAjax(map);
        }
        return error();
    }


    /**
     * 通用下载请求
     *
     * @param url 文件路径
     * @param exp 超时时间
     * @return 结果
     */
    @SneakyThrows
    @GetMapping("/download")
    public ResponseEntity<byte[]> fileDownload(@RequestParam("url") String url, @RequestHeader("user-agent") String userAgent, @RequestParam(name = "fileName", required = false) String fileName, @RequestParam(name = "exp", required = false) Long exp, @RequestParam(name = "isDelete", required = false) boolean isDelete) {
        File file = fileService.readBytes(ApiUtils.decodeBase64(url));
        byte[] body = FileUtils.getBytesByFile(file);

        if (!fileName.contains(".")) {
            fileName += ".zip";
            if (isDelete) {
                file.delete();
            }
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentLength(body.length);

        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        ContentDisposition disposition = ContentDisposition.builder("attachment").filename(FileUtils.setFileDownloadHeader(userAgent, fileName)).build();
        headers.setContentDisposition(disposition);
        return new ResponseEntity<>(body, headers, HttpStatus.OK);
    }

    @PostMapping("/unzip/{fileId}")
    public Result unzip(@PathVariable Long fileId) {
        boolean res = fileService.unzip(fileId, getUserId());
        return toAjax(res);
    }

    @PostMapping("/zip")
    public Result zip(Long[] fileIds) {
        boolean res = fileService.zip(fileIds, getUserId());
        return toAjax(res);
    }
}
